﻿#!/usr/bin/env python
# -*- coding: utf-8 -*-

'customized class uages'

__author__='zhaoxp'

"""
定制话class，主要是通过定制class中的类来实现各个功能，主要有：
1 __init__ 初始化类，可以定制多个__init__方法，但只有最后一个起作用（看来这要是语言本身的特性）。
2 __str__和__repr__这两个是显示对象用，__repr__主要是调试用，在命令行窗口显示用。
3 __iter__和next(self)，这两个配合使用是用来做循环功能的，例如for n in MyObject()：
4 __getitem__ 这个用来实现类似数组取值的方式，用法为s[3],s[4]等。也可以实现slice，那么需要调整代码，参考下面例子。
5 __getattr__ 这个用来定义通过.attr的方式获取属性值时如何返回。
6 __call__ 把实例本身做调用，例如 s=Student()  s()
"""

class Student(object):
	'This is my class representing student'
	# 下面这个变量属于各个实例共享的变量，即Java中的static变量
	stdCount=0
	
	def __init__(self):
		self.__name=""
	def __init__(self,name,sex):
		self.__name=name
		self.__sex=sex
	# 最后一个__init__方法起作用
	def __init__(self,name):
		self.__name=name
		Student.stdCount+=1
	def __len__(self):
		return len(self.__name)
	def __str__(self):
		return 'Student object (name=%s)'% self.__name
	# __repr__和__str__的区别在于，在python命令行直接输入对象名，显示的是__repr__，而如果在程序中（比如字符串相加）
	# 显示的是__str__，所以__repr__是为调试服务，对开发者有用
	# 这里也可以定义一个方法：__repr__()
	# 下面是偷懒的写法
	__repr__=__str__
	
	# 注意这个方法的返回值。
	# 从测试例子可以看出，当使用 实例名.属性名 的方式获取属性值时，系统先找有没有这个属性，如果没有，
	# 则取调用__getattr__这个方法。
	# 如果没有返回值，那么调用的结果为None，这是因为方法默认返回值为None，所以你也可以自己定义是否抛出异常等。
	# 另外，这里的attr可以定义属性，也可以定义方法。如果是定义方法，那么应该返回方法。
	def __getattr__(self,attr):
		if attr=='score':
			return 99
		if attr=='getAge':
			return lambda x:x+10
		return AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
	
	def __call__(self):
		print 'My name is %s' % self.__name
		
	def __del__(self):
		Student.stdCount-=1
		print "Student object destroyed -->",self.__class__.__name__,self.__name
	
class Fib(object):
	def __init__(self):
		self.a,self.b=0,1
	def __iter__(self):
		return self
	def next(self):
		self.a,self.b=self.b,self.a+self.b
		if self.a>10000:
			raise StopIteration()
		return self.a
	def __getitem__(self,n):
		if isinstance(n,int):
			a,b=1,1
			for x in range(n):
				a,b=b,a+b
			return a
		if isinstance(n,slice):
			start=n.start
			stop=n.stop
			a,b=1,1
			L=[]
			for x in range(stop):
				if x>=start:
					L.append(a)
				a,b=b,a+b
			return L
		return "error"
	def __str__(self):
		return "Fib:iteration example"
		
class Vector(object):
	def __init__(self,a,b):
		self.x=a
		self.y=b
	def __str__(self):
		return 'Vector (%d, %d)' % (self.x,self.y)
	# 运算符重载
	def __add__(self,other):
		return Vector(self.x+other.x,self.y+other.y)
	
if __name__=='__main__':
	print "customized class uage example"
	print "Student.__doc__ =",Student.__doc__
	print "Student.__name__ =",Student.__name__
	print "Student.__module__ =",Student.__module__
	print "Student.__bases__ =",Student.__bases__
	print "Student.__dict__ =",Student.__dict__
	s=Student('Tom')
	s2=Student('Jack')
	print "s=Student('Tom') =",s
	print "name len(s) =",len(s)
	print "s.name =",s.name
	print "s.score =",s.score
	print "s.sex =",s.sex
	print "s.getAge(13) =",s.getAge(13)
	print "s() =",s()
	del s2 # invoke __del__
	f=Fib()
	print "f=Fib() =",f
	for n in f:
		print "Fib iteration:",n
	print "f[5] =",f[5]
	print "f[11] =",f[11]
	print "f[38] =",f[38]
	print "f[5,13] =",f[5:13]
	print "f[-1,3] =",f[-1,3]
	v1=Vector(3,12)
	v2=Vector(2,-4)
	v3=v1+v2
	print "v1=Vector(3,12) =",v1
	print "v2=Vector(2,-4) =",v2
	print "v3=v1+v2 =",v3
	